package com.micai.boss.base.oss;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;

/**
 * 描述：oss工具类
 * <p>
 *
 * @author: 赵新国
 * @date: 2018/4/23 14:30
 */
public class AliOssClient {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private  String imgBucketName = "risklocal";
    private  String desBucketName = "risklocal";
    private  String privateBucketName = "risklocal";
    private  String contractBucketName = "koala-contract";
    private  String riskBucketName = "risklocal";
    private static final String endpoint ="http://oss-cn-beijing.aliyuncs.com";
    private static final String accessKeyId = "VvT5IcBWb6M94EMh";
    private static final String accessKeySecret = "N9CNo7Df5wfkwXXxAQGJEgNHfnY0aU";
    private static OSSClient instance = null;

    public AliOssClient(String imgBucketName, String desBucketName,String privateBucketName){
        this.imgBucketName = imgBucketName;
        this.desBucketName = desBucketName;
        this.privateBucketName = privateBucketName;
        instance = new OSSClient(endpoint, accessKeyId, accessKeySecret);
    }

    public AliOssClient(String imgBucketName, String desBucketName,String privateBucketName,String _endpoint){
        this.imgBucketName = imgBucketName;
        this.desBucketName = desBucketName;
        this.privateBucketName = privateBucketName;
        instance = new OSSClient(_endpoint, accessKeyId, accessKeySecret);
    }

    private  OSSClient getOSSClient() {
        return instance;
    }

    /**
     * 接受图片流并保存到oss，最好封装一层服务来调用<br>
     * 名字前加上自己业务的前缀比如用户加“user/”<br>
     * 自己保证名字的唯一性和后缀的正确性<br>
     * @param content
     * @param picName 图片在oss存储的key值
     * @throws IOException
     */
    public boolean putImage(InputStream content, String picName) {
        try {
            if (StringUtils.isBlank(picName) || content == null || content.available() < 10 ) {
                return false;
            }
            OSSClient client = getOSSClient();
            ObjectMetadata meta = new ObjectMetadata();
            // 必须设置ContentLength
            meta.setContentLength(content.available());
            meta.setContentType(ContentTypeEnum.IMAGE.getDes());
            // 上传Object.
            client.putObject(imgBucketName, picName, content, meta);
            return true;
        } catch (Exception e) {
            logger.error("oss放图片异常", e);
            return false;
        } finally {
            if (content != null) {
                try {
                    content.close();
                } catch (IOException e) {
                    logger.error("关闭图片流异常", e);
                }
            }
        }
    }

    /**
     * 将String类型数据保存到OSS
     *
     * @param content
     * @param key 描述内容在oss的key值
     * @throws IOException
     */
    public  boolean putString(String content, String key){
        if (StringUtils.isBlank(key) || content == null) {
            return false;
        }
        ByteArrayInputStream stringInputStream = null;
        try {
            OSSClient client = getOSSClient();
            ObjectMetadata meta = new ObjectMetadata();
            // 上传Object.
            stringInputStream = new ByteArrayInputStream(content.getBytes("UTF-8"));
            // 必须设置ContentLength
            meta.setContentLength(stringInputStream.available());
            client.putObject(desBucketName, key, stringInputStream, meta);
            return true;
        } catch (Exception e) {
            logger.error("oss放字符串信息异常", e);
            return false;
        } finally {
            if (stringInputStream != null) {
                try {
                    stringInputStream.close();
                } catch (IOException e) {
                    logger.error("关闭字符流异常", e);
                }
            }
        }
    }

    /**
     * 根据key返回在OSS中的内容
     *
     * @param key
     * @return
     * @throws IOException
     */
    public String getString(String key)  {
        String result = null;
        InputStream objectContent = null;
        try {
            OSSClient client = getOSSClient();
            OSSObject object = client.getObject(desBucketName, key);
            objectContent = object.getObjectContent();
            result = IOUtils.toString(objectContent, "UTF-8");
            return result;
        } catch (Exception e) {
            logger.error("oss获取字符串信息异常,key:"+key, e);
            return result;
        } finally {
            if (objectContent != null) {
                try {
                    objectContent.close();
                } catch (IOException e) {
                    logger.error("关闭输入流异常", e);
                }
            }
        }
    }

    /**
     * 字符串类型copy
     * @param sourceKey
     * @param desKey
     * @return
     */
    public boolean copyString(String sourceKey,String desKey){
        return copyObject(sourceKey, desKey, desBucketName, desBucketName);
    }

    /**
     * 根据在oss中的key和文件类型获得输入流<br>
     * contentTypeEnum用来提供文件类型,oss根据这个决定获取的bucket<br>
     * 如果获取的key不存在或者发生其它异常会返回null
     * @param key
     * @param bucketName
     * @return
     */
    public InputStream getInputStream(String key, String bucketName) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        OSSClient client = getOSSClient();
        InputStream objectContent = null;
        try {
            OSSObject object = client.getObject(bucketName, key);
            objectContent = object.getObjectContent();
        } catch (Exception e) {
            logger.error("获取oss输入流异常key:"+key, e);
            return null;
        }
        return objectContent;
    }

    /**
     * 根据key删除oss上的图片
     *
     * @param key
     */
    public boolean deleteImg(String key) {
        if (StringUtils.isBlank(key)) {
            return false;
        }
        try {
            OSSClient client = getOSSClient();
            client.deleteObject(imgBucketName, key);
            return true;
        } catch (Exception e) {
            logger.error("删除oss信息异常" + key, e);
            return false;
        }
    }

    /**
     * 得到风控图片文件
     * @param key
     * @return
     */
    public File getRiskImageFile(String key) {
        InputStream inputStream = getInputStream(key, riskBucketName);
        if(inputStream == null) {
            logger.error("获取oss认证图片为空 key{} bucket{}", key, riskBucketName);
            return null;
        }
        String fileName = key.substring(key.lastIndexOf("/") + 1);
        int lastIndexOf = fileName.lastIndexOf(".");
        String prefix = null;
        String suffix = null;
        if(lastIndexOf == -1) {
            prefix = fileName;
            suffix = "";
        } else {
            prefix = fileName.substring(0, fileName.lastIndexOf("."));
            suffix = fileName.substring(fileName.lastIndexOf(".") );
        }
        return getFilebyInputStream(inputStream, prefix, suffix);
    }

    /**
     * 图片重命名
     * @param oldName
     * @param newName
     */
    public boolean reNameImg(String oldName, String newName) {
        if (StringUtils.isBlank(oldName) || StringUtils.isBlank(newName)) {
            return false;
        }
        InputStream inputStream = null;
        try {
            OSSClient client = getOSSClient();
            if (StringUtils.equals(oldName, newName)) {
                OSSObject ossObject = client.getObject(imgBucketName, oldName);
                inputStream = ossObject.getObjectContent();
                return true;
            }
            client.copyObject(imgBucketName, oldName, imgBucketName, newName);
            client.deleteObject(imgBucketName, oldName);
            return true;
        } catch (Exception e) {
            logger.error("oss图片操作异常" , e);
            return false;
        }finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    logger.error("关闭输入流异常", e);
                }
            }
        }
    }

    /**
     * copy对象
     * @param oldName
     * @param newName
     * @param oldBucket
     * @param newBucket
     * @return
     */
    public boolean copyObject(String oldName, String newName, String oldBucket, String newBucket) {
        if (StringUtils.isBlank(oldName) || StringUtils.isBlank(newName) || StringUtils.isBlank(oldBucket)
                || StringUtils.isBlank(newBucket)) {
            return false;
        }
        InputStream inputStream = null;
        try {
            OSSClient client = getOSSClient();
            if (StringUtils.equals(oldName, newName) && StringUtils.equals(oldBucket, newBucket)) {
                OSSObject  object =      client.getObject(oldBucket, oldName);
                inputStream = object.getObjectContent();
                return true;
            }
            client.copyObject(oldBucket, oldName, newBucket, newName);
            return true;
        } catch (Exception e) {
            logger.error("oss复制图片操作异常", e);
            return false;
        }finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    logger.error("关闭输入流异常", e);
                }
            }
        }
    }

    /**
     * 创建新存储空间
     * @param bucketName
     * @return
     */
    public boolean createBucket(String bucketName) {
        try {
            OSSClient client = getOSSClient();
            // 新建一个Bucket
            client.createBucket(bucketName);
            client.setBucketAcl(bucketName, CannedAccessControlList.Private);
            return true;
        } catch (Exception e) {
            logger.error("oss创建bucket异常", e);
            return false;
        }
    }

    /**
     * 上传私有文件到阿里云
     * @param content
     * @param key
     * @return
     */
    public boolean putPrivateObject(InputStream content, String key) {
        try {
            if (StringUtils.isBlank(key) || content == null || content.available() < 10) {
                return false;
            }
            OSSClient client = getOSSClient();
            ObjectMetadata meta = new ObjectMetadata();
            // 必须设置ContentLength
            meta.setContentLength(content.available());
            // 上传Object.
            PutObjectResult putObject = client.putObject(privateBucketName, key, content, meta);
            System.out.println(putObject.toString());
            return true;
        } catch (Exception e) {
            logger.error("oss放私有资源异常", e);
            return false;
        } finally {
            if (content != null) {
                try {
                    content.close();
                } catch (IOException e) {
                    logger.error("关闭输入要流异常", e);
                }
            }
        }
    }

    /**
     * 获取授权Url,只有存放在私有bucket里需要强访问控制的资源需要进行
     * @param key
     * @param time
     * @return
     */
    public String getAuthUrl(String key,long time) {
        Date expires = new Date(new Date().getTime() + time); // 60 minute
        OSSClient client = getOSSClient();
        GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(privateBucketName,
                key);
        generatePresignedUrlRequest.setExpiration(expires);
        URL url = client.generatePresignedUrl(generatePresignedUrlRequest);
        return url.toString();
    }

    public static File getFilebyInputStream(InputStream inputStream, String prefix, String suffix) {
        File file = null;
        try {
            file = File.createTempFile(prefix, suffix);
            file.deleteOnExit();
        } catch (IOException e2) {
            e2.printStackTrace();
        }
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file);
            byte[] b = new byte[1024];
            int end = 0;
            while((end = inputStream.read(b, 0, 1024)) != -1){
                outputStream.write(b, 0, end);
            }
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }

    /**
     * 上传借款合同到阿里云
     * @param content
     * @param key
     * @return
     */
    public boolean putContractObject(InputStream content, String key) {
        try {
            if (StringUtils.isBlank(key) || content == null || content.available() < 10) {
                return false;
            }
            OSSClient client = getOSSClient();
            ObjectMetadata meta = new ObjectMetadata();
            // 必须设置ContentLength
            meta.setContentLength(content.available());
            // 上传Object.
            PutObjectResult putObject = client.putObject(contractBucketName, key, content, meta);
            System.out.println(putObject.toString());
            return true;
        } catch (Exception e) {
            logger.error("oss放私有资源异常", e);
            return false;
        } finally {
            if (content != null) {
                try {
                    content.close();
                } catch (IOException e) {
                    logger.error("关闭输入要流异常", e);
                }
            }
        }
    }

    /**
     * 获得合同输入流
     * 根据在oss中的key和文件类型获得输入流<br>
     * 如果获取的key不存在或者发生其它异常会返回null
     * @param key
     * @return
     */
    public InputStream getContractInputStream(String key) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        OSSClient client = getOSSClient();
        InputStream objectContent = null;
        try {
            OSSObject object = client.getObject(contractBucketName, key);
            objectContent = object.getObjectContent();
        } catch (Exception e) {
            logger.error("获取oss输入流异常key:"+key, e);
            return null;
        }
        return objectContent;
    }

    public static void main(String[] args) throws FileNotFoundException {
//        AliOssClient aliOssClient = new AliOssClient("risktest","risktest","risktest");
//        aliOssClient.createBucket("risk_test");
//        boolean putPrivateObject = aliOssClient.putPrivateObject(new FileInputStream(".classpath"), "shaoyn/20160118/api/classpath");
//        InputStream inputStream = aliOssClient.getInputStream("shaoyn/20160118/api/classpath");
//        File filebyInputStream = getFilebyInputStream(inputStream, "shaoyn/20160118/api/classpath");
//        System.out.println(filebyInputStream.getName());
//        InputStream inputStream = aliOssClient.getInputStream("liugang/20151012/api/a.classpath", ContentTypeEnum.TXT);
//        String next = new Scanner(inputStream).useDelimiter("\\A").next();
//        System.out.println(next);
    }
}
